﻿package com.calefk.util {

	import flash.events.AsyncErrorEvent;
	import flash.events.IOErrorEvent;
	import flash.events.NetStatusEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.NetConnection; 
	import flash.net.Responder;
	import com.calefk.util.Logger;
    
	/**
	 * Controlador que permite guardar en BD a travez de la libreria AMFPHP 
	 */
	public class AMFConnect {	
        
        /*public static var instance:cnDatabase = null;
        
        private static function getInstance():cnDatabase {
            if (instance == null) {
                instance = new cnDatabase();
            }
            return instance;
        }
        
        public static function startConnection(urlServer:String , api:String):void {
            var ins:cnDatabase = getInstance();
            ins._startConnection(urlServer , api);
        }
        
		public static function callMethod(api_and_method:String , exeFunction:Function , ... arg):void {
             var ins:cnDatabase = getInstance();
             var funCall:Function = ins._callMethod;
             arg.unshift(exeFunction);
             arg.unshift(api_and_method);
			 funCall.apply(ins , arg)
        }*/
		
		/*La variable conexion del tipo NetConnection es la que permitirá la comunicación*/ 
		private var connection:NetConnection;
		/*Esta variable se encarga del os valores que son regresados por el servidor, 
		ya se si es exitosa o no la conexión*/ 
		private var responder:Responder;
		
		/* variables que sirven para guardar el objeto que debe reaccionar al cumplirse una llamada
		 * y la función a realizar al recibirla */
		private var receiverFunction:Function = null;
		
		private var currentCall:String;
		public var URL_SERVER:String;
		public var API:String;
		
		public function AMFConnect(urlServer:String , api:String) { 
			connection = new NetConnection(); 
			/* Establecemos una conexión Ida/Vuelta entre el Flash y el servidor */ 
			URL_SERVER = urlServer;
			API = api;
			
			connection.addEventListener(IOErrorEvent.IO_ERROR , onIOError , false , 0 , true);
			connection.addEventListener(NetStatusEvent.NET_STATUS , onStatus , false , 0 , true);
			connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
			connection.addEventListener(AsyncErrorEvent.ASYNC_ERROR , async_error , false , 0 , true);
			connection.connect(URL_SERVER + API); 
		}
		
		private function async_error(e:AsyncErrorEvent):void {
			Logger.error("async_error : " + e.text);
		}
		
		private function securityErrorHandler(e:SecurityErrorEvent):void {
			Logger.error("SecurityErrorHandler : " + e.text);
		}
		
		private function onStatus(e:NetStatusEvent):void {
			if (e.info.level == "error") {
				Logger.error("Status NextConnection : " + e.info.code);
				if (e.info.code == "NetConnection.Call.Failed") {
					Logger.error("NextConnection: La URL no es valida");
				}
			}
		}
		
		private function onIOError(e:IOErrorEvent):void {
			Logger.error("IOError NextConnection : " + e.text);
		}
		
		public function callMethod(api_and_method:String , exeFunction:Function , ... arg):void {
			responder = new Responder(respuesta, error); 
			receiverFunction = exeFunction;
			currentCall = api_and_method;
			
			// se usa apply para poder enviar los parametros con ... ,
			// sino no es posible enviar ese tipo de paraemtros
			var funCall:Function = connection.call;
			arg.unshift(responder);
			arg.unshift(api_and_method);
			funCall.apply(connection , arg);
			//connection.call(api_and_method , responder, arg); 
		}
		/*
		public static function getGeneral(exeFunction:Function):void {
			responder = new Responder(cnDatabase.respuesta, cnDatabase.error); 
			receiverFunction = exeFunction;
			connection.call("Gameservice.getGeneral", responder); 
			currentCall = "getGeneral";
		}
		
		public static function getAllQuestions(exeFunction:Function):void {
			responder = new Responder(cnDatabase.respuesta, cnDatabase.error); 
			receiverFunction = exeFunction;
			connection.call("Gameservice.getAllQuestions", responder); 
			currentCall = "getAllQuestions";
		}
		
		public static function getLevels(exeFunction:Function):void {
			responder = new Responder(cnDatabase.respuesta, cnDatabase.error); 
			receiverFunction = exeFunction;
			connection.call("Gameservice.getLevels", responder); 
			currentCall = "getLevels";
		}
		
		public static function getCategories(exeFunction:Function):void {
			responder = new Responder(cnDatabase.respuesta, cnDatabase.error); 
			receiverFunction = exeFunction;
			connection.call("Gameservice.getCategories", responder); 
			currentCall = "getCategories";
		}
		
		public static function getAllQuestionRound(exeFunction:Function):void {
			responder = new Responder(cnDatabase.respuesta, cnDatabase.error); 
			receiverFunction = exeFunction;
			connection.call("Gameservice.getAllQuestionsRound", responder); 
			currentCall = "getAllQuestionsRound";
		}*/		
		
		/*Esta función se ejecuta en caso de ÉXITO tras ejecutar el método call, pasándole como 
		parámetro un objeto con el resultado regresado.*/
		private function respuesta(resultado:Object):Object {
			if (receiverFunction != null) {
				// si tenemos una función por realizar lo hacemos
				var func:Function = receiverFunction;
				// borrar referencias
				receiverFunction = null;
				// ejecutar metodo
				func(resultado);

			}
			return resultado;
		} 

		/*Esta función se ejecuta en caso de FRACASO tras ejecutar el método call, pasándole como 
		parámetro el objeto del error.*/ 
		private function error(error:Object):Object {
			Logger.error("cnDatabase : error call " + currentCall);
			for each(var p:* in error) {
				Logger.error("cnDatabase.error : " + p + " : " + error[p]);
			}
			return error;
		} 
        /**
         * Duplica la conexion actual , se utiliza cuando queremos tener 2 conexiones sin afectarse una con otra
         * @return
         */
        public function clone():AMFConnect {
            var cn:AMFConnect = new AMFConnect(URL_SERVER , API);
            return cn;            
        }

	}

}